
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/route.h>
#include <arpa/inet.h>
#include <sys/sysinfo.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/netlink.h>
#include <linux/pfkeyv2.h>
// #include <line.hpp>

const char * get_sadb_msg_type(int type) {

    static char buffer[100];
    bzero(buffer,100);
    switch (type)
    {
    case SADB_RESERVED: return "Reserved";
        /* code */
        break;
    case SADB_GETSPI:   return "Get SPI";
    case SADB_UPDATE:   return "Update";
    case SADB_ADD:      return "Add";
    case SADB_DELETE:   return "Delete";
    case SADB_GET:      return "Get";
    case SADB_ACQUIRE:  return "Acquire";
    case SADB_REGISTER: return "Register";
    case SADB_EXPIRE:   return "Expire";
    case SADB_FLUSH:    return "Flush";
    case SADB_DUMP:     return "Dump";
    default:
        sprintf(buffer,"[Unknow type %d]",type);
        return buffer;
        break;
    }
}

void print_sadb_msg(struct sadb_msg * msg, int size) {

    printf("SADB MSG INFORMATION\n");
    printf("sadb_msg_version = %d\n", msg->sadb_msg_version);
    printf("sadb_msg_type = %d\n", msg->sadb_msg_type);
    printf("sadb_msg_errno = %d\n", msg->sadb_msg_errno);
    printf("sadb_msg_satype = %d\n", msg->sadb_msg_satype);
    printf("sadb_msg_len = %d\n", msg->sadb_msg_len);
    printf("sadb_msg_reserved = %d\n", msg->sadb_msg_reserved);
    printf("sadb_msg_seq = %d\n", msg->sadb_msg_seq);
    printf("sadb_msg_pid = %d\n", msg->sadb_msg_pid);
}

void sadb_dump(int type) {

    int s;
    char buffer[4096];
    struct sadb_msg msg;

    int goteof;

    s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);

    bzero(&msg, sizeof(msg));
    msg.sadb_msg_version = PF_KEY_V2;
    msg.sadb_msg_type    = SADB_DUMP;
    msg.sadb_msg_satype  = type;
    msg.sadb_msg_len     = sizeof(msg) / 8;
    msg.sadb_msg_pid     = getpid();

    printf("Sending dump message:\n");
    print_sadb_msg(&msg, sizeof(msg));

    write(s, &msg, sizeof(msg));
    
    printf("\nMessages returned:\n");

    goteof = 0;
    while (goteof == 0) {

        int     msglen = 0;
        struct sadb_msg * msgp;
        msglen = read(s, &buffer, 4096);
        msgp = (struct msgdb_msg*)buffer;
        print_sadb_msg(msgp, msglen);

        if (msgp->sadb_msg_seq == 0) {

            goteof = 1;
        }
    }
}

int main(int argc, char * argv[]) {

    int satype = SADB_SATYPE_UNSPEC;
    printf("pid = %d\n", getpid());
    getopt(argc, argv,"t:");

    sadb_dump(satype);
    return EXIT_SUCCESS;
}

// gcc dump.c -o dump


